package com.why.simpleboot.core.core.factory;

import com.why.simpleboot.core.annotation.ioc.Component;
import com.why.simpleboot.core.annotation.schedule.Scheduled;

import com.why.simpleboot.core.core.aop.proxy.NoProxyMethodName;
import com.why.simpleboot.core.core.schedule.Task.FunctionTask;
import com.why.simpleboot.core.core.schedule.Task.InternalTask;
import com.why.simpleboot.core.core.schedule.Task.TaskType;
import com.why.simpleboot.core.core.schedule.Task.TimeoutTask;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @program: why-simpleboot-framework
 * @description:
 * @author: @why
 * @create: 2021-05-29 17:00
 **/
public class ScheduleFactory {
    private final Set<FunctionTask> functionTasks = new HashSet<>();

    public void loadSchedules(ClassFactory classFactory, BeanFactory beanFactory) {
        Set<Class<?>> classes = classFactory.getCLASSES().get(Component.class);
        for (Class<?> aClass : classes) {
            for (Method method : aClass.getMethods()) {
                if (method.isAnnotationPresent(Scheduled.class) && !NoProxyMethodName.isProxyMethod(method.getName())) {
                    Scheduled scheduled = method.getAnnotation(Scheduled.class);
                    Object bean = beanFactory.getBeanByType(aClass);
//                    如果延时为0，那就任务其是一个间隔任务，否则认为其是一个延时任务
                    if (scheduled.initialDelay() == 0) {
                        functionTasks.add(new InternalTask(method, bean, null, TaskType.TASK_TYPE_SCHEDULE_INTERVAL, scheduled.fixedRate()));
                    } else if (scheduled.initialDelay() != 0) {
                        functionTasks.add(new TimeoutTask(method, bean, null, TaskType.TASK_TYPE_SCHEDULE_TIMEOUT, scheduled.fixedRate()));
                    }

                }
            }

        }
        new ScheduleHandler().run();
    }

    private final class ScheduleHandler {
        private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors() * 2);

        public void run() {
            for (FunctionTask task : functionTasks) {
//           间隔任务
                Scheduled scheduled = task.getMethod().getAnnotation(Scheduled.class);
                if (task.getTaskType() == TaskType.TASK_TYPE_SCHEDULE_INTERVAL) {
                    /**
                     * command：执行线程
                     * initialDelay：初始化延时
                     * period：两次开始执行最小间隔时间
                     * unit：计时单位
                     */
                    scheduledExecutorService.scheduleAtFixedRate(task, scheduled.initialDelay(), scheduled.fixedRate(), TimeUnit.MILLISECONDS);
                } else if (task.getTaskType() == TaskType.TASK_TYPE_SCHEDULE_TIMEOUT) {
                    /**
                     * 这就是一个延迟执行
                     */
                    scheduledExecutorService.schedule(task, scheduled.initialDelay(), TimeUnit.MILLISECONDS);
                    /**
                     * public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                     *
                     * long initialDelay,
                     *
                     * long delay,
                     *
                     * TimeUnit unit);
                     *
                     * command：执行线程
                     * initialDelay：初始化延时
                     * period：前一次执行结束到下一次执行开始的间隔时间（间隔执行延迟时间）
                     * unit：计时单位
                     */
                }

            }

        }
    }
}
